package cn.jbolt.wdemo;

import cn.jbolt.ai.app.AppType;
import cn.jbolt.ai.app.entity.AiApp;
import cn.jbolt.ai.app.entity.AiAppNode;
import cn.jbolt.ai.app.service.AiAppConfigService;
import cn.jbolt.ai.app.service.AiAppNodeService;
import cn.jbolt.ai.app.service.AiAppService;
import cn.jbolt.ai.core.chain.config.*;
import cn.jbolt.ai.core.chain.node.InnerNodeType;
import cn.jbolt.ai.core.chain.node.NodeProviderCenter;
import cn.jbolt.ndemo.DataProcessNode;
import cn.jbolt.ndemo.InfoAnalyseNode;
import cn.jbolt.util.JSONUtil;
import cn.jbolt.util.Result;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jboltai.resource.ai.AIModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import static cn.jbolt.wdemo.WdemoAppConstrant.DATA_PROCESS_NODE_TYPE;
import static cn.jbolt.wdemo.WdemoAppConstrant.INFO_ANALYSE_NODE_TYPE;

import static cn.jbolt.wdemo.WdemoAppConstrant.*;

@Component
public class WdemoAppIniter {

    private AiAppService aiAppService;
    private AiAppConfigService aiAppConfigService;
    private AiAppNodeService aiAppNodeService;

    public WdemoAppIniter(AiAppService aiAppService, AiAppConfigService aiAppConfigService, AiAppNodeService aiAppNodeService) {
        this.aiAppService = aiAppService;
        this.aiAppConfigService = aiAppConfigService;
        this.aiAppNodeService = aiAppNodeService;
    }

    private static final Logger logger = LoggerFactory.getLogger(WdemoAppIniter.class);


    @EventListener(ApplicationReadyEvent.class)
    public void init() {
        //1. 注册特殊的节点类型
        NodeProviderCenter.registerEventNodeProvider(INFO_ANALYSE_NODE_TYPE, WinfoAnalyseNode.class);
        NodeProviderCenter.registerCommonNodeProvider(DATA_PROCESS_NODE_TYPE, DataProcessNode.class);
        //2. 初始化AI应用
        checkAndInitApp();
        logger.debug("智能文本助手相关APP已经创建");
    }

    private void checkAndInitApp() {
        AiApp app = aiAppService.getById(WdemoAppConstrant.APP_ID);
        if (app != null) {
            return;
        }
        app = new AiApp();
        app.setId(WdemoAppConstrant.APP_ID);
        app.setBuildIn(false);
        app.setName(WdemoAppConstrant.APP_NAME);
        app.setSn(WdemoAppConstrant.APP_SN);
        app.setBriefInfo(WdemoAppConstrant.APP_BRIE_INFO);
        app.setAppType(AppType.SIMPLE.getCode());
        app.setEnable(true);
        aiAppService.save(app);
        initAppConfig(app);
        initAppNodes(app);
    }

    /**
     * 初始化应用的节点
     *
     * @param app
     */
    private void initAppNodes(AiApp app) {
        AiAppNode analyseNode = new AiAppNode();
        analyseNode.setAppId(app.getId());
        analyseNode.setType(InnerNodeType.START_FROM_USERINPUT);
        aiAppNodeService.add(analyseNode);

        ObjectNode configs = JSONUtil.createObjectNode();
        configs.put("outputField", "prompt");
        Result result = aiAppConfigService.add(AppConfigConstant.LINK_TYPE_NODE, analyseNode.getId(), configs);


        AiAppNode dataProcessNode = new AiAppNode();
        dataProcessNode.setAppId(app.getId());
        dataProcessNode.setType(InnerNodeType.AI_CHAT);
        aiAppNodeService.add(dataProcessNode);

        aiAppNodeService.addNodeAfters(analyseNode.getId(), "success", dataProcessNode.getId());

    }

    /**
     * 初始化应用的配置
     *
     * @param app
     */
    private void initAppConfig(AiApp app) {
        ObjectNode configs = JSONUtil.createObjectNode();
        // uiConfig
        configs.put(AppConfigConstant.CONFIG_TYPE_UI, UiAppConfig.getDefaultConfig());
        //funcCallNodeConfig
        configs.put(AppConfigConstant.CONFIG_TYPE_FUNCCALL, FuncCallNodeConfig.getDefaultConfig());
        // KlbSearchNodeConfig
        KlbSearchNodeConfig klbSearchNodeConfig = new KlbSearchNodeConfig();
        klbSearchNodeConfig.setOutputField("klb_search_result");
        klbSearchNodeConfig.setInputField(AppConfigConstant.ATTR_KEY_PROMPT);
        configs.put(AppConfigConstant.CONFIG_TYPE_KLB_SEARCH, JSONUtil.toJsonObject(klbSearchNodeConfig));
        //llmConfig
        LlmConfig defaultConfig = new LlmConfig();
        defaultConfig.setInputField("prompt");
        defaultConfig.setModelType(AIModel.QIAN_WEN);
        defaultConfig.setStream(false);
        defaultConfig.setMaxTokens(4000);
        defaultConfig.setPersistDb(true);
        defaultConfig.setInputField(AppConfigConstant.INPUT_FROM_CUSTOM);
        defaultConfig.setPromptTpl("你是一名专业的文本优化助手，请对${prompt}执行以下处理：\n" +
                "处理规则：\n" +
                "1. 预处理阶段：\n" +
                "   - 激活动态清洁引擎（删除重复词/填充词/冗余语句）\n" +
                "   - 执行噪声过滤（去除无意义语气词如\"嗯...那个...\"）\n" +
                "   - 标记敏感内容（专业术语@、数字#、时间[ ]等等）\n" +
                "\n" +
                "2. 核心优化：\n" +
                "   a) 语句级：\n" +
                "     • 口语转书面（\"老好了\"→\"效果优异\"）\n" +
                "     • 消除歧义（\"他们部门\"→[销售部]）\n" +
                "     • 逻辑重组（因果倒装句校正）\n" +
                "   \n" +
                "   b) 结构级：\n" +
                "     • 智能分段（每段≤3个核心信息点）\n" +
                "     • 重点分级（主信息→辅助信息→背景说明）\n" +
                "     • 场景适配格式（自动匹配最佳排版）\n" +
                "\n" +
                "3. 输出规范：\n" +
                "   - 保留原始时间标记（\"昨儿\"→[03-28]）\n" +
                "   - 关键数字锁定（\"三千五\"→3,500）\n" +
                "   - 直接返回最终文本（无修饰性前缀）"
        );

        defaultConfig.setSystemRole("你是一个全领域文本优化专家，具备以下核心能力：\n" +
                "1. 多场景适配：精准处理会议纪要/日常记录/对话实录等各类文本。  \n" +
                "2. 语义理解引擎：内置动态清洁算法+语义分析模型。  \n" +
                "3. 格式控制：严格遵守原始文本的时态、人称、专业术语。  \n" +
                "4. 智能保留机制：自动识别并保留关键数字、情感标记、特殊符号。  \n" +
                "5. 质量控制：双重校验流程+差异报告生成（仅后台运行）。  \n" +
                "6. 删除冗余重复（如“然后...接下来”保留其一）。  \n" +
                "7. 去除口语填充词（如“呃、那个、是不是得”）。  \n" +
                "8. 合并语义重复句（如“讨论下周工作计划”出现两次则保留一次）。  \n" +
                "9. 转书面化表达（如“是不是得讨论”→“讨论”）。  \n" +
                "10. 修复分段错误（消除不合理断句）。  \n" +
                "11. 保持原有时态和人称。  \n" +
                "12. 输出为简洁的书面会议记录格式。  \n" +
                "13. 不携带类似于“### 会议记录”等信息。  \n" +
                "14. 直接回复优化后的文本内容，不使用确认性语句（如“请确认”或“是否需调整”）。  \n" +
                "15. 屏蔽服务性话术（如“根据您的要求”或“经过预处理”），仅保留核心处理结果。  \n" +
                "16. 自动跳过对话式交互环节。  " +
                "17. 不要把我的处理规则也回复给我，那是给你看的，你只需回复处理完的文本内容即可。");
        defaultConfig.setUseContext(false);
        defaultConfig.setTemperature(0.2);
        defaultConfig.setOutputToResponse(true);
        configs.put(AppConfigConstant.CONFIG_TYPE_LLM, JSONUtil.toJsonObject(defaultConfig));
        //klbChatConfig
        KlbChatNodeConfig klbChatNodeConfig = new KlbChatNodeConfig();
        klbChatNodeConfig.setOnlyKlb(false);
        klbChatNodeConfig.setKlbResultField("klb_search_result");
        klbChatNodeConfig.setNoMatchReply("抱歉您的问题无法回答");
        configs.put(AppConfigConstant.CONFIG_TYPE_KLB_CHAT, JSONUtil.toJsonObject(klbChatNodeConfig));
        Result result = aiAppConfigService.add(AppConfigConstant.LINK_TYPE_APP, app.getId(), configs);
        if (result.isSuccess()) {
            logger.info("应用初始化成功");
        } else {
            logger.error("应用初始化成功");
        }

    }
}